package view.protocol;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.rmi.RemoteException;

import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import server.FirewallException;
import server.NotExpertException;
import server.Protocol;
import server.ReadWriteException;
import view.ErrorFrame;
import view.Globals;
import view.HelpFrame;
import view.Settings;
import view.StatusBar;

import controller.FirewallSession;

/**
 *   Protocol Management Frame.
 */
public  class ProtocolFrame extends JFrame
{
	/**
	 * 
	 */
	private static final long serialVersionUID = -6926282588129958256L;
	public static ProtocolFrame currentProtocolFrame = null;
	
	public  ProtocolTable protocolTable = null;
	/**
	 * server controller
	 */
	protected FirewallSession UI;
	
	/**
	 * ProtocolFrame constructor: create instance of frame
	 */
	public ProtocolFrame(FirewallSession ui)
	{	
		super("Protocols");
		UI = ui;
		
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		setSize(Globals.protocolFrameSize);
		setLayout(new BorderLayout());
		
		/*Standart buttons for the frame*/
		addStandartButtons();
		try {
			if ( UI.isExpert() ){
				Box buttons = getButtons();
				add(buttons, BorderLayout.NORTH);
			}
		}  catch (RemoteException e1) {
			ErrorFrame.AddError("Failed to create protocol frame:" + e1.getMessage(), new JFrame());
		}
		
		/* Tables for the frame */
		JPanel protocols = getProtocolTable();
		if(protocols != null)
		{
			add(protocols, BorderLayout.CENTER);
		}
		StatusBar.register(this);
		setLocationRelativeTo(null);
	}
	
	/**
	 * Adds standard buttons.
	 */
	private void addStandartButtons()
	{
		Box tableBox = Box.createHorizontalBox();
		
		JButton finish = new JButton("Finish");
		finish.setToolTipText("Close and save changes");
		JButton cancel = new JButton("Cancel");
		cancel.setToolTipText("Close without saving changes");
		JButton help = new JButton("Help");
		cancel.setToolTipText("Help for rules screen");
		
		tableBox.add(help);		
		tableBox.add(finish);
		tableBox.add(cancel);
	    
		
		/*Help button listener - open the relevant help */		
		help.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) 
			{
				protocolsHelp();
			}	  
		});
		
		/*Finish button listener - closes the frame*/		
		finish.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) 
			{
				dispose();				
			}	  
		});
		  
		/*Cancel button listener - closes the frame*/	
		cancel.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) 
			{
				dispose();			
			}	  
		});

	    add(tableBox, BorderLayout.SOUTH);
	}

	/**
	 * Adds the two rules tables
	 */
	protected JPanel getProtocolTable()
	{
		/* Panel for rules */
		JPanel table = new JPanel(new BorderLayout());
		
		/* Table */
		protocolTable = new ProtocolTable(Settings.DEFAULT_PROTOCOL_WINDOW_DEPTH, UI);
		
		/* Header adding */
		table.add(protocolTable.getProtocolTableHeader(), BorderLayout.CENTER);
		protocolTable.getTableHeader().setReorderingAllowed(false);	
		
		/* Table adding */
		JScrollPane scrollpane = new JScrollPane(protocolTable);
		scrollpane.getViewport().setPreferredSize(new Dimension(200,230));
		table.add(scrollpane,  BorderLayout.SOUTH);
		
		return table;
	}
	
	/**
	 * Adds buttons for ruleset loading, saving and reseting
	 * @throws RemoteException 
	 */
	protected Box getButtons() throws RemoteException 
	{		
		/* Button for loading */	
		Box buttons = Box.createVerticalBox();
		boolean isReadWrite = UI.isReadWrite();	
		JButton add = new JButton("Add Protocol    ");
		add.setToolTipText("Add new protocol to database");
		
		add.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) 
			{
				ProtocolDialog frame = new ProtocolDialog(UI, null);
				frame.setVisible(true);
			}	  
		});
		if (!isReadWrite)
			add.setEnabled(false);
		buttons.add(add);

		/* Button for saving */		
		JButton edit = new JButton("Edit Protocol    ");
		edit.setToolTipText("Edit existed protocol in database");
		
		edit.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) 
			{
				int[] selectedRows = currentProtocolFrame.protocolTable.getSelectedRows();
				
				/* delete the selected in tables rule in ruleset, update windows */
				if((selectedRows.length == 0) )
				{
			    	ErrorFrame.AddError("You need to select protocol to edit!",new JFrame());				
			    	return;
				}
				
				for(int i = 0; i < selectedRows.length; i++)
				{
					String name = (String) currentProtocolFrame.protocolTable.getValueAt(selectedRows[i],0);
					if (  ! ( name == null || name.equals("") ) ){
						String in = (String) currentProtocolFrame.protocolTable.getValueAt(selectedRows[i],1);
						String out = (String) currentProtocolFrame.protocolTable.getValueAt(selectedRows[i],2);
						ProtocolDialog frame = new ProtocolDialog(UI, new Protocol(name, in, out));
						frame.setVisible(true);
					}
				}
			}	  
		});
		if (!isReadWrite)
			edit.setEnabled(false);
		
		buttons.add(edit);		
	
		/* Button for reseting */	
		JButton delete = new JButton("Delete Protocol");
		delete.setToolTipText("Delete protocol from database");
		if (!isReadWrite)
			delete.setEnabled(false);
		
		buttons.add(delete);
		delete.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) 
			{
				try {
					int[] selectedRows = currentProtocolFrame.protocolTable.getSelectedRows();
					
					/* delete the selected in tables rule in ruleset, update windows */
					if((selectedRows.length == 0) )
					{
				    	throw new Exception("You need to select protocol to delete in table");				
				   }
					
					for(int i = 0; i < selectedRows.length; i++)
					{
						String name = (String) currentProtocolFrame.protocolTable.getValueAt(selectedRows[i],0);
						if (  ! ( name == null || name.equals("") ) )
							UI.deleteProtocol(name);
					}
				} catch (RemoteException e1) {
					ErrorFrame.AddError("Remote connection error:" + e1.getMessage(), new JFrame());
				} catch (FirewallException e1) {
					ErrorFrame.AddError("Firewall internal error:" + e1.getMessage(), new JFrame());
				} catch (ReadWriteException e1) {
					ErrorFrame.AddError("You can not change DB. DataBase is Read only!" + e1.getMessage(), new JFrame());
				} catch (NotExpertException e1) {
					ErrorFrame.AddError("You are not allowed to do any changes in DB, you have to login as an expert." + e1.getMessage(), new JFrame());
				} catch (Exception e1) {
					ErrorFrame.AddError("Error: can't delete rule: " + e1.getMessage(), new JFrame());
				}
				
				/* Build the appropriate table */
				currentProtocolFrame.protocolTable.build();
			}	  
		});
		

		return buttons;	
	}

	/**Create if not exists protocol frame.
	 * @return current Protocol frame 	
	 *  */
	public static ProtocolFrame getInstance(FirewallSession ui)
	{
		if(currentProtocolFrame == null)
		{
			currentProtocolFrame = new ProtocolFrame(ui);
		}
		
		currentProtocolFrame.protocolTable.build();
		return currentProtocolFrame;
	}
	
	
	/**
	 * Show help action for Protocol Frame.
	 */
	protected void protocolsHelp() 
	{
		HelpFrame.currentHelpFrame.ShowDesc(Globals.REG_EXP);	
	}
}